//! 修复命令的集成测试
//! 
//! 测试修复后的哈希操作、DECRBY命令和CLUSTER命令在实际服务器中的表现
//! 使用真实的Redis客户端连接和RESP协议通信

use crate::common::*;
use redis::{Client, Commands, Connection, RedisResult, ErrorKind, RedisError};
use std::time::Duration;
use tokio::time::sleep;

/// 测试修复后的哈希操作功能
mod hash_operations_integration_tests {
    use super::*;
    
    #[tokio::test]
    async fn test_hset_hget_fixed_implementation() {
        let env = TestEnvironment::new();
        let mut server_manager = TestServerManager::new(8100);
        
        // 启动优化服务器（包含修复的哈希操作）
        let server = server_manager.create_optimized_server().await
            .expect("Failed to start optimized server");
        
        sleep(Duration::from_millis(200)).await;
        
        let client = Client::open(format!("redis://{}", server.address()))
            .expect("Failed to create Redis client");
        
        let mut conn = client.get_connection()
            .expect("Failed to connect to Redis server");
        
        // 测试基本的HSET/HGET操作
        let set_result: i32 = conn.hset("test_hash", "field1", "value1")
            .expect("HSET command should work");
        assert_eq!(set_result, 1, "Setting new field should return 1");
        
        let get_result: String = conn.hget("test_hash", "field1")
            .expect("HGET command should work");
        assert_eq!(get_result, "value1", "HGET should return correct value");
        
        // 测试TYPE命令能正确识别哈希类型
        let type_result: String = conn.cmd("TYPE").arg("test_hash").query()
            .expect("TYPE command should work");
        assert_eq!(type_result, "hash", "TYPE should correctly identify hash");
        
        // 测试更新现有字段
        let update_result: i32 = conn.hset("test_hash", "field1", "new_value")
            .expect("HSET update should work");
        assert_eq!(update_result, 0, "Updating existing field should return 0");
        
        let updated_value: String = conn.hget("test_hash", "field1")
            .expect("HGET after update should work");
        assert_eq!(updated_value, "new_value", "Value should be updated");
        
        // 测试多个字段
        let _: i32 = conn.hset("test_hash", "field2", "value2")
            .expect("Setting second field should work");
        
        let field2_value: String = conn.hget("test_hash", "field2")
            .expect("Getting second field should work");
        assert_eq!(field2_value, "value2", "Second field should have correct value");
        
        // 清理
        server_manager.stop_all().await.expect("Failed to stop servers");
        env.cleanup().await;
    }
    
    #[tokio::test]
    async fn test_hdel_and_cleanup() {
        let env = TestEnvironment::new();
        let mut server_manager = TestServerManager::new(8110);
        
        let server = server_manager.create_optimized_server().await
            .expect("Failed to start optimized server");
        
        sleep(Duration::from_millis(200)).await;
        
        let client = Client::open(format!("redis://{}", server.address()))
            .expect("Failed to create Redis client");
        
        let mut conn = client.get_connection()
            .expect("Failed to connect to Redis server");
        
        // 设置多个字段
        let _: i32 = conn.hset("test_hash", "field1", "value1").unwrap();
        let _: i32 = conn.hset("test_hash", "field2", "value2").unwrap();
        
        // 删除一个字段
        let del_result: i32 = conn.hdel("test_hash", "field1")
            .expect("HDEL should work");
        assert_eq!(del_result, 1, "Deleting existing field should return 1");
        
        // 验证字段已删除
        let get_result: RedisResult<String> = conn.hget("test_hash", "field1");
        assert!(get_result.is_err() || get_result.unwrap().is_empty(), "Deleted field should not exist");
        
        // 验证其他字段仍存在
        let field2_value: String = conn.hget("test_hash", "field2")
            .expect("Other fields should remain");
        assert_eq!(field2_value, "value2");
        
        // 验证类型仍为hash
        let type_result: String = conn.cmd("TYPE").arg("test_hash").query()
            .expect("TYPE command should work");
        assert_eq!(type_result, "hash", "TYPE should still be hash with remaining fields");
        
        // 删除最后一个字段
        let _: i32 = conn.hdel("test_hash", "field2").unwrap();
        
        // 验证哈希已被清理
        let final_type: String = conn.cmd("TYPE").arg("test_hash").query()
            .expect("TYPE command should work");
        assert_eq!(final_type, "none", "TYPE should be none after deleting all fields");
        
        server_manager.stop_all().await.expect("Failed to stop servers");
        env.cleanup().await;
    }
    
    #[tokio::test]
    async fn test_hash_edge_cases() {
        let env = TestEnvironment::new();
        let mut server_manager = TestServerManager::new(8120);
        
        let server = server_manager.create_optimized_server().await
            .expect("Failed to start optimized server");
        
        sleep(Duration::from_millis(200)).await;
        
        let client = Client::open(format!("redis://{}", server.address()))
            .expect("Failed to create Redis client");
        
        let mut conn = client.get_connection()
            .expect("Failed to connect to Redis server");
        
        // 测试特殊字符
        let _: i32 = conn.hset("test_hash", "field:with:colons", "value with spaces").unwrap();
        let special_value: String = conn.hget("test_hash", "field:with:colons").unwrap();
        assert_eq!(special_value, "value with spaces");
        
        // 测试空值
        let _: i32 = conn.hset("test_hash", "empty_field", "").unwrap();
        let empty_value: String = conn.hget("test_hash", "empty_field").unwrap();
        assert_eq!(empty_value, "");
        
        // 测试Unicode
        let _: i32 = conn.hset("test_hash", "中文字段", "中文值").unwrap();
        let unicode_value: String = conn.hget("test_hash", "中文字段").unwrap();
        assert_eq!(unicode_value, "中文值");
        
        server_manager.stop_all().await.expect("Failed to stop servers");
        env.cleanup().await;
    }
}

/// 测试修复后的DECRBY命令功能
mod decrby_integration_tests {
    use super::*;
    
    #[tokio::test]
    async fn test_decr_decrby_fixed_implementation() {
        let env = TestEnvironment::new();
        let mut server_manager = TestServerManager::new(8130);
        
        let server = server_manager.create_optimized_server().await
            .expect("Failed to start optimized server");
        
        sleep(Duration::from_millis(200)).await;
        
        let client = Client::open(format!("redis://{}", server.address()))
            .expect("Failed to create Redis client");
        
        let mut conn = client.get_connection()
            .expect("Failed to connect to Redis server");
        
        // 测试DECR命令
        let decr_result: i64 = conn.cmd("DECR").arg("counter").query()
            .expect("DECR should work");
        assert_eq!(decr_result, -1, "DECR on non-existing key should return -1");
        
        // 设置初始值
        let _: () = conn.set("counter", 10).unwrap();
        
        let decr_result2: i64 = conn.cmd("DECR").arg("counter").query()
            .expect("DECR should work");
        assert_eq!(decr_result2, 9, "DECR should decrease by 1");
        
        // 测试DECRBY命令
        let decrby_result: i64 = conn.cmd("DECRBY").arg("counter").arg(3).query()
            .expect("DECRBY should work");
        assert_eq!(decrby_result, 6, "DECRBY should decrease by specified amount");
        
        server_manager.stop_all().await.expect("Failed to stop servers");
        env.cleanup().await;
    }
    
    #[tokio::test]
    async fn test_decrby_error_handling() {
        let env = TestEnvironment::new();
        let mut server_manager = TestServerManager::new(8140);
        
        let server = server_manager.create_optimized_server().await
            .expect("Failed to start optimized server");
        
        sleep(Duration::from_millis(200)).await;
        
        let client = Client::open(format!("redis://{}", server.address()))
            .expect("Failed to create Redis client");
        
        let mut conn = client.get_connection()
            .expect("Failed to connect to Redis server");
        
        // 测试无效的递减值
        let invalid_result: RedisResult<i64> = conn.cmd("DECRBY").arg("counter").arg("not_a_number").query();
        assert!(invalid_result.is_err(), "DECRBY with invalid number should return error");
        
        if let Err(e) = invalid_result {
            match e.kind() {
                ErrorKind::ResponseError => {
                    assert!(e.to_string().contains("not an integer"), 
                           "Error message should indicate invalid integer");
                },
                _ => {
                    // 某些Redis客户端可能将其解释为其他类型的错误
                    println!("Got error: {}", e);
                }
            }
        }
        
        // 测试缺少参数的情况
        let missing_arg_result: RedisResult<i64> = conn.cmd("DECRBY").arg("counter").query();
        assert!(missing_arg_result.is_err(), "DECRBY with missing argument should return error");
        
        server_manager.stop_all().await.expect("Failed to stop servers");
        env.cleanup().await;
    }
    
    #[tokio::test] 
    async fn test_decrby_boundary_conditions() {
        let env = TestEnvironment::new();
        let mut server_manager = TestServerManager::new(8150);
        
        let server = server_manager.create_optimized_server().await
            .expect("Failed to start optimized server");
        
        sleep(Duration::from_millis(200)).await;
        
        let client = Client::open(format!("redis://{}", server.address()))
            .expect("Failed to create Redis client");
        
        let mut conn = client.get_connection()
            .expect("Failed to connect to Redis server");
        
        // 测试零递减
        let _: () = conn.set("counter", 10).unwrap();
        let zero_decr: i64 = conn.cmd("DECRBY").arg("counter").arg(0).query()
            .expect("DECRBY with 0 should work");
        assert_eq!(zero_decr, 10, "DECRBY with 0 should not change value");
        
        // 测试负数递减（相当于增加）
        let negative_decr: i64 = conn.cmd("DECRBY").arg("counter").arg(-5).query()
            .expect("DECRBY with negative number should work");
        assert_eq!(negative_decr, 15, "DECRBY with negative number should increase value");
        
        server_manager.stop_all().await.expect("Failed to stop servers");
        env.cleanup().await;
    }
}

/// 测试修复后的CLUSTER命令功能（需要集群服务器）
mod cluster_commands_integration_tests {
    use super::*;
    
    // 注意：这些测试需要实际的集群服务器，可能需要特殊配置
    #[tokio::test]
    #[ignore] // 默认忽略，因为需要集群配置
    async fn test_cluster_info_command() {
        let env = TestEnvironment::new();
        let mut server_manager = TestServerManager::new(8160);
        
        // 尝试启动集群服务器
        let server = server_manager.create_cluster_server().await
            .expect("Failed to start cluster server");
        
        sleep(Duration::from_millis(500)).await; // 集群启动可能需要更长时间
        
        let client = Client::open(format!("redis://{}", server.address()))
            .expect("Failed to create Redis client");
        
        let mut conn = client.get_connection()
            .expect("Failed to connect to cluster server");
        
        // 测试CLUSTER INFO命令
        let info_result: String = conn.cmd("CLUSTER").arg("INFO").query()
            .expect("CLUSTER INFO should work");
        
        assert!(info_result.contains("cluster_state"), "INFO should contain cluster_state");
        assert!(info_result.contains("cluster_slots_assigned"), "INFO should contain slots info");
        
        server_manager.stop_all().await.expect("Failed to stop servers");
        env.cleanup().await;
    }
    
    #[tokio::test]
    #[ignore] // 默认忽略，因为需要集群配置
    async fn test_cluster_nodes_command() {
        let env = TestEnvironment::new();
        let mut server_manager = TestServerManager::new(8170);
        
        let server = server_manager.create_cluster_server().await
            .expect("Failed to start cluster server");
        
        sleep(Duration::from_millis(500)).await;
        
        let client = Client::open(format!("redis://{}", server.address()))
            .expect("Failed to create Redis client");
        
        let mut conn = client.get_connection()
            .expect("Failed to connect to cluster server");
        
        // 测试CLUSTER NODES命令
        let nodes_result: String = conn.cmd("CLUSTER").arg("NODES").query()
            .expect("CLUSTER NODES should work");
        
        assert!(!nodes_result.is_empty(), "NODES should return node information");
        
        server_manager.stop_all().await.expect("Failed to stop servers");
        env.cleanup().await;
    }
    
    #[tokio::test]
    #[ignore] // 默认忽略，因为需要集群配置
    async fn test_cluster_slots_command() {
        let env = TestEnvironment::new();
        let mut server_manager = TestServerManager::new(8180);
        
        let server = server_manager.create_cluster_server().await
            .expect("Failed to start cluster server");
        
        sleep(Duration::from_millis(500)).await;
        
        let client = Client::open(format!("redis://{}", server.address()))
            .expect("Failed to create Redis client");
        
        let mut conn = client.get_connection()
            .expect("Failed to connect to cluster server");
        
        // 测试CLUSTER SLOTS命令
        let slots_result: Vec<Vec<redis::Value>> = conn.cmd("CLUSTER").arg("SLOTS").query()
            .expect("CLUSTER SLOTS should work");
        
        assert!(!slots_result.is_empty(), "SLOTS should return slot allocation");
        
        server_manager.stop_all().await.expect("Failed to stop servers");
        env.cleanup().await;
    }
    
    #[tokio::test]
    #[ignore] // 默认忽略，因为需要集群配置
    async fn test_cluster_keyslot_command() {
        let env = TestEnvironment::new();
        let mut server_manager = TestServerManager::new(8190);
        
        let server = server_manager.create_cluster_server().await
            .expect("Failed to start cluster server");
        
        sleep(Duration::from_millis(500)).await;
        
        let client = Client::open(format!("redis://{}", server.address()))
            .expect("Failed to create Redis client");
        
        let mut conn = client.get_connection()
            .expect("Failed to connect to cluster server");
        
        // 测试CLUSTER KEYSLOT命令
        let slot_result: i64 = conn.cmd("CLUSTER").arg("KEYSLOT").arg("testkey").query()
            .expect("CLUSTER KEYSLOT should work");
        
        assert!(slot_result >= 0 && slot_result < 16384, "Slot should be in valid range");
        
        // 测试相同键的一致性
        let slot_result2: i64 = conn.cmd("CLUSTER").arg("KEYSLOT").arg("testkey").query()
            .expect("CLUSTER KEYSLOT should work");
        
        assert_eq!(slot_result, slot_result2, "Same key should always map to same slot");
        
        server_manager.stop_all().await.expect("Failed to stop servers");
        env.cleanup().await;
    }
}

/// 综合测试：验证修复不影响其他功能
mod comprehensive_integration_tests {
    use super::*;
    
    #[tokio::test]
    async fn test_fixed_commands_with_basic_operations() {
        let env = TestEnvironment::new();
        let mut server_manager = TestServerManager::new(8200);
        
        let server = server_manager.create_optimized_server().await
            .expect("Failed to start optimized server");
        
        sleep(Duration::from_millis(200)).await;
        
        let client = Client::open(format!("redis://{}", server.address()))
            .expect("Failed to create Redis client");
        
        let mut conn = client.get_connection()
            .expect("Failed to connect to Redis server");
        
        // 测试基本操作仍然工作
        let _: () = conn.set("string_key", "string_value").unwrap();
        let string_result: String = conn.get("string_key").unwrap();
        assert_eq!(string_result, "string_value");
        
        // 测试修复的哈希操作
        let _: i32 = conn.hset("hash_key", "field1", "value1").unwrap();
        let hash_result: String = conn.hget("hash_key", "field1").unwrap();
        assert_eq!(hash_result, "value1");
        
        // 测试修复的数值操作
        let _: () = conn.set("number_key", 100).unwrap();
        let decr_result: i64 = conn.cmd("DECRBY").arg("number_key").arg(10).query().unwrap();
        assert_eq!(decr_result, 90);
        
        // 验证不同类型的TYPE检测
        let string_type: String = conn.cmd("TYPE").arg("string_key").query().unwrap();
        assert_eq!(string_type, "string");
        
        let hash_type: String = conn.cmd("TYPE").arg("hash_key").query().unwrap();
        assert_eq!(hash_type, "hash");
        
        let number_type: String = conn.cmd("TYPE").arg("number_key").query().unwrap();
        assert_eq!(number_type, "string"); // 数字以字符串形式存储
        
        server_manager.stop_all().await.expect("Failed to stop servers");
        env.cleanup().await;
    }
    
    #[tokio::test]
    async fn test_concurrent_operations_on_fixed_commands() {
        let env = TestEnvironment::new();
        let mut server_manager = TestServerManager::new(8210);
        
        let server = server_manager.create_optimized_server().await
            .expect("Failed to start optimized server");
        
        sleep(Duration::from_millis(200)).await;
        
        let server_address = server.address();
        
        // 创建多个并发连接
        let handles = (0..5).map(|i| {
            let address = server_address.clone();
            tokio::spawn(async move {
                let client = Client::open(format!("redis://{}", address))
                    .expect("Failed to create Redis client");
                
                let mut conn = client.get_connection()
                    .expect("Failed to connect to Redis server");
                
                // 每个连接执行不同的操作
                for j in 0..10 {
                    let hash_key = format!("concurrent_hash_{}", i);
                    let field = format!("field_{}", j);
                    let value = format!("value_{}_{}", i, j);
                    
                    // 哈希操作
                    let _: i32 = conn.hset(&hash_key, &field, &value).unwrap();
                    let retrieved: String = conn.hget(&hash_key, &field).unwrap();
                    assert_eq!(retrieved, value);
                    
                    // 数值操作
                    let counter_key = format!("counter_{}", i);
                    let _: () = conn.set(&counter_key, j * 10).unwrap();
                    let _: i64 = conn.cmd("DECRBY").arg(&counter_key).arg(1).query().unwrap();
                }
                
                i
            })
        }).collect::<Vec<_>>();
        
        // 等待所有任务完成
        for handle in handles {
            handle.await.expect("Concurrent task failed");
        }
        
        server_manager.stop_all().await.expect("Failed to stop servers");
        env.cleanup().await;
    }
}